package com.oreilly.ez.base;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.oreilly.ez.entity.SysLog;
import com.oreilly.ez.repo.SysLogRepo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;

@Aspect
@Component
@Order(1)
@Slf4j
public class AopLog {



    private static ObjectMapper mapper = new ObjectMapper();

    @Autowired
    private SysLogRepo sysLogRepo;
//    private Gson gson = new Gson();

    @Pointcut("execution(public * com.oreilly.ez.web..*.*(..))")
    private void controllerAspect() {

    }


    @Before(value = "controllerAspect()")
    public void methodBefore(JoinPoint jp) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        if(requestAttributes != null){

            HttpServletRequest request = requestAttributes.getRequest();

            String requestId = request.getHeader("X-requestId");

            Object[] args = jp.getArgs();
            String params = Arrays.toString(args);

            String targetClass = jp.getTarget().getClass().toString();

            //打印请求内容
            log.info("===============请求内容===============");
            log.info("请求地址:" + request.getRequestURL().toString());
            log.info("请求class:" + targetClass);

            String method = request.getMethod();
            log.info("请求方式:" + method);
            log.info("请求类方法:" + jp.getSignature());

            log.info("请求类方法参数:" + params);
            log.info("===============请求内容===============");


            // save log
            SysLog sysLog = new SysLog();
            sysLog.setRequestId(requestId);
            sysLog.setUdate(new Date());
            sysLog.setParams(params);

            MethodSignature signature = (MethodSignature) jp.getSignature();
            SysNote annotation = signature.getMethod().getAnnotation(SysNote.class);
            if (annotation != null) {
                String name = annotation.name();
                sysLog.setTitle(name);
            } else {

                sysLog.setTitle(jp.getSignature().getName());
            }
            sysLog.setMethod(jp.getSignature().toString());
            sysLogRepo.save(sysLog);


            //auto set udate = now()
            String name = jp.getSignature().getName();
//        log.info(name);
//        if ("save".equalsIgnoreCase(name)) {
//
//            for (Object arg : args) {
//                String className = arg.getClass().getName();
//                System.out.println("className = " + className);
//                Method[] methods = arg.getClass().getMethods();
//                for (Method m : methods) {
//                    if (m.getName().equals("setUdate")) {
//                        try {
//                            m.invoke(arg, new Date());
//                        } catch (IllegalAccessException e) {
//                            e.printStackTrace();
//                        } catch (InvocationTargetException e) {
//                            e.printStackTrace();
//                        }
//                    }
//                }
//            }
//        }
        }

    }


    @AfterReturning(value = "controllerAspect()", returning = "o")
    public void methodAfter(Object o) throws Exception {

        log.info("--------------返回内容----------------");
        log.info("Response内容:" + mapper.writeValueAsString(o));
        log.info("--------------返回内容----------------");
    }


    //    @Pointcut("@annotation(com.web.springbootaoplog.config.Log)")
//    public void pointcut() {}
    @Around("controllerAspect()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object result = null;
        long beginTime = System.currentTimeMillis();
        log.info("我在目标方法之前执行！");
        result = point.proceed();
        long endTime = System.currentTimeMillis();

        log.info("time = {} ms", (endTime - beginTime));
        return result;
    }


}
